import { Service } from 'egg';
import { Op } from 'sequelize';
import areas from '../util/area';
import { v4 as uuidv4 } from 'uuid';
import { Result } from '../util/result';
import MsgEnum from '../util/msgEnum';

export default class Company extends Service {
  /**
   * 展示企业列表
   * @param page 当前页
   * @param pageSize 每页展示数目
   * @param name 企业名
   * @param medicalField 医疗领域
   * @return { companyList, total } 企业数组和企业总数
   */
  public async showList(
    page: number,
    pageSize: number,
    name: string | undefined,
    medicalField: string | undefined
  ) {
    const whereStr: { name?: {}, medical_field?: {} } = {};
    if (name) {
      whereStr.name = { [Op.like]: `%${name}%` };
    }
    if (medicalField) {
      // eslint-disable-next-line dot-notation
      whereStr['medical_field'] = medicalField;
    }
    const { rows, count: total } = await this.ctx.model.Company.findAndCountAll({
      where: whereStr,
      offset: (page - 1) * pageSize,
      limit: pageSize,
      include: [
        {
          model: this.ctx.model.CompanyType,
          attributes: ['name'],
        },
        {
          model: this.ctx.model.MedicalField,
          attributes: ['name'],
        },
        {
          model: this.ctx.model.MainBusiness,
          attributes: ['uuid', 'name'],
          through: { attributes: [] }
        },
      ],
      attributes: [
        'id',
        'uuid',
        'name',
        'address',
        'companyNum',
        'createTime',
        'description',
        'filler'
      ]
    });

    const companyList = rows.map(companyItem => {
      const {
        createTime,
        MedicalField,
        MainBusinesses,
        CompanyType
      } = companyItem.dataValues;
      let createDate = '-';
      if (createTime) {
        createDate = (createTime.getFullYear()) + '-' +
          (createTime.getMonth() + 1) + '-' +
          (createTime.getDate());
      }
      const medicalField = MedicalField?.name;
      const type = CompanyType?.name;
      let mainBusiness = '';
      MainBusinesses.forEach(businessItem => {
        mainBusiness += businessItem.name + ';';
      });
      return {
        medicalField,
        mainBusiness,
        createDate,
        type,
        ...companyItem.dataValues
      };
    });

    return {
      companyList,
      total
    };
  }

  public async insert(address,
    addressBefore,
    companyNum,
    createDate,
    description,
    filler,
    name,
    mainBusiness,
    medicalField,
    type) {
    const { ctx } = this;
    let transaction;
    try {
      transaction = await ctx.model.transaction();
      let add = addressBefore.join(';');
      if (address) add += `;${address}`;
      const comp = await ctx.model.Company.create({
        address: add,
        uuid: uuidv4(),
        companyNum,
        createTime: createDate,
        description,
        filler,
        name,
        medicalField,
        type,
        updateTime: new Date(),
      }, { transaction });
      const mb = await ctx.model.MainBusiness.findAll({ where: { uuid: { [Op.in]: mainBusiness } }, transaction });
      await comp.setMainBusinesses(mb, { transaction });
      transaction.commit();
    } catch (e) {
      transaction.rollback();
      console.log(e);
      return { success: false, reason: e };
    }
    return { success: true };
  }

  public async update(
    uuid,
    address,
    addressBefore,
    companyNum,
    createDate,
    description,
    filler,
    name,
    mainBusiness,
    medicalField,
    type) {
    const { ctx } = this;
    let transaction;
    try {
      transaction = await ctx.model.transaction();
      const comp = await ctx.model.Company.findOne({ where: { uuid }, transaction });
      let createTime = createDate;
      if (!createDate) {
        // 未填写创建时间
        createTime = null;
      }
      await comp.update({
        address: addressBefore.join(';') + ';' + address ?? '',
        companyNum,
        createTime,
        description,
        filler,
        name,
        medicalField,
        type,
        updateTime: new Date(),
      }, { transaction });
      const mb = await ctx.model.MainBusiness.findAll({ where: { uuid: { [Op.in]: mainBusiness } }, transaction });
      await comp.setMainBusinesses(mb, { transaction });
      transaction.commit();
    } catch (e) {
      transaction.rollback();
      console.log(e);
      return { success: false, reason: e };
    }
    return { success: true };
  }

  public async getCompanyMedication() {
    const { ctx } = this;
    const companys = await ctx.model.Company.findAll();
    const comResult: any = [];
    const data = companys.map(async v => {
      const medicalField = await v.getMedicalField({ attributes: ['name'], });
      const name = medicalField.dataValues.name;
      if (comResult.hasOwnProperty(name)) {
        comResult[name]++;
      } else {
        comResult[name] = 1;
      }
    });
    await Promise.all(data);
    const typeName: any = [];
    const typeResult: any = [];
    for (const dataResKey in comResult) {
      typeName.push(dataResKey);
      typeResult.push(comResult[dataResKey]);
    }


    return [
      { typeName, typeResult },
    ];
  }

  public async delete(id) {
    const { ctx } = this;
    const result = ctx.model.transaction(async t => {
      // 先删除 merge 表
      await ctx.model.MergeCompanyMainbusiness.destroy({
        where: { fk_company_id: id }
      }, { transaction: t });
      // 后删除company 表
      await ctx.model.Company.destroy({
        where: { id }
      }, { transaction: t });
    });
    return result;
  }

  public async bulkDelete(batchDeleteArray: string[]) {
    const { ctx } = this;
    const result = ctx.model.transaction(async t => {
      // 先删除 merge 表
      await ctx.model.MergeCompanyMainbusiness.destroy({
        where: { fk_company_id: { [Op.in]: batchDeleteArray } }
      }, { transaction: t });
      // 后删除company 表
      await ctx.model.Company.destroy({
        where: { id: { [Op.in]: batchDeleteArray } }
      }, { transaction: t });
    });
    return result;
  }

  public async getAllCompanyType() {
    const mainData = await this.ctx.model.Company.findAll({
      attributes: ['type'], include: [{
        model: this.ctx.model.CompanyType,
        required: true,
        attributes: ['name']
      }]
    });
    console.log(mainData);
    const types: any = {};
    const dataw: any = [];
    mainData.forEach((v: { CompanyType: { name: string } }) => {
      if (types.hasOwnProperty(v.CompanyType.name)) {
        types[v.CompanyType.name]++;

      } else {
        types[v.CompanyType.name] = 1;
      }
    });
    for (const name in types) {
      if (types.hasOwnProperty(name)) {
        dataw.push({ type: name, value: types[name] });
      }
    }
    return dataw;
  }

  public async getCompanyMap() {
    const mainData = await this.ctx.model.Company.findAll({ attributes: ['address'] });
    const data: any = {};
    mainData.forEach((v: any) => {
      let add;
      if (v.address?.split(';')[0] === '台湾省') {
        add = '台湾';
      } else {
        add = v.address?.split(';')[1];
      }
      if (!data.hasOwnProperty(add)) {
        data[add] = 1;
      } else {
        data[add]++;
      }
    });
    let dataw = 'lng,lat,name,v\n';
    for (const name in data) {
      if (data.hasOwnProperty(name)) {

        if (areas[name] && name !== undefined && name !== 'undefined') {
          dataw += (areas[name]?.join(',') ?? '0,0') + ',' + name + ',' + data[name] + '\n';
        } else {
          dataw += '\n';
        }
      }
    }
    return dataw;
  }

  public async bulkIncrease(batchIncreaseArray: string[]) {
    // FIXME: 待实现批量插入
    const { ctx } = this;
    const result = ctx.model.transaction(async t => {
      await ctx.model.Company.bulkCreate(batchIncreaseArray, { transaction: t });
    });
    return result;
  }

  public async getCompanyDetail(uuid) {
    const { ctx } = this;
    return await ctx.model.Company.findOne({
      where: { uuid },
      include: [{ model: ctx.model.MainBusiness, attributes: ['uuid', 'name'] }]
    });
  }

  async insertCompanies(datas, filler) {
    const { ctx } = this;
    let num = 0;

    for (const data of datas) {
      let transaction;
      try {
        transaction = await ctx.model.transaction();
        console.log(data);
        const mf = await ctx.model.MedicalField.findOne({ where: { name: data[3] } });
        const t = await ctx.model.CompanyType.findOne({ where: { name: data[4] } });
        const comp = await ctx.model.Company.create({
          uuid: uuidv4(),
          name: data[0],
          companyNum: data[1],
          address: data[2],
          medicalField: mf.uuid,
          type: t.uuid,
          createTime: data[6],
          description: data[7],
          filler,
          updateTime: new Date(),
        }, { transaction });
        const mb = await ctx.model.MainBusiness.findAll({
          where: { name: { [Op.in]: data[5].split(';') } },
          transaction
        });
        await comp.setMainBusinesses(mb, { transaction });
        transaction.commit();
        num = num + 1;
      } catch (e) {
        console.log(e);

        await transaction.rollback();
        return new Result(null, MsgEnum.SERVER_ERROR);
      }
    }

    return new Result(
      { upload: true },
      `${num}个企业已上传成功。`
    );
  }


}

